function renderModelOptionRow(optionId, option) {
    var containerCell = renderContainerCell(optionId, option);

    var yesCell = renderVoteAnswerCell('y', optionId, option);
    var noCell = renderVoteAnswerCell('n', optionId, option);
    var maybeCell = renderVoteAnswerCell('m', optionId, option);

    return '<tr id="' + optionId + '">' + containerCell //
	    + yesCell + noCell + maybeCell + '</tr>';

}

function renderContainerCell(optionId, option) {
    var containerId = 'container_caption_' + optionId;
    var containerAttributes = createAttribute('id', containerId);

    var forceEditForm = checkIfCaptionShouldBeEdited(optionId);

    var content;
    if (option.caption == '' || forceEditForm) {
	content = renderCaptionEditForm(optionId);
    } else {
	content = renderContainerCellContent(optionId,
		escapeHtml(option.caption));
    }

    return '<td ' + containerAttributes + '>' + content + '</td>';
}


function checkIfCaptionShouldBeEdited(optionId) {
    for ( var idx in fieldsToBeEdited) {
	var currOptionId = fieldsToBeEdited[idx];
	if (optionId == currOptionId) {
	    fieldsToBeEdited.splice(idx, 1);
	    return true;
	}
    }
    return false;
}


function renderContainerCellContent(optionId, caption) {
    var captionLine = _renderCaptionSpan(optionId, caption);

    var copyLink = renderEventLink('Copy', "copyOption('" + optionId + "');",
	    null, 'mini');
    var removeLink = renderEventLink('Remove', "removeOption('" + optionId
	    + "');", null, 'mini');

    var attr = createAttribute("id", 'cmd_' + optionId);
    var commandLine = '<span ' + attr + '>' + copyLink + '&nbsp;' + removeLink
	    + '</span>';

    return captionLine + '<BR>' + commandLine;
}


function _renderCaptionSpan(optionId, caption) {
    var spanOnClickHandler = "editCaption('" + optionId + "\'); return false;";
    var spanAttributes = createAttribute('id', 'caption_' + optionId)
	    + createAttribute('onClick', spanOnClickHandler);

    var state = wave.getState();
    var isLocked = (state.get('locked', 0) == 1);
    if (isWaveHost() || !isLocked) {
	spanAttributes += createAttribute('class', 'optioncanbeeditedcaption');
    }

    return '<span ' + spanAttributes + '>' + escapeHtml(caption) + '</span>';
}

function renderVoteAnswerCell(vote, optionId, option) {
    var content = renderVoteOption(optionId, vote);

    var tdAttr = createAttribute('id', 'votings:' + optionId + ':' + vote)
	    + createAttribute('class', vote + 'box');

    return '<td ' + tdAttr + '>' + content + '</td>';
}

function renderVoteOption(optionId, vote) {
    var handler = "addVote('" + optionId + "', '" + vote + "');";
    var voteLink = renderEventLink('Vote here', handler);

    var divAttr = createAttribute('id', "votepanel_" + optionId + "::" + vote)
	    + createAttribute('class', 'voteoption');
    var content = '<div ' + divAttr + '>' + voteLink + '</div>';

    return content;
}

function renderCaptionEditForm(optionId) {
    var fieldId = 'captionedit_' + optionId;
    var currentCaption = model.options[optionId].caption;
    return renderSimpleEditForm("saveCaption('" + optionId + "');", fieldId,
	    currentCaption);
}


function renderSimpleEditForm(actionHandler, inputFieldID, inputFieldValue) {

    var template_simple_edit_form = '<form onSubmit="<!--HANDLER--> return false;" '
	    + '   style="margin:0px;">'
	    + ' <input type="text" id="<!--INPUT_FIELD_ID-->" '
	    + '   value="<!--INPUT_FIELD_VALUE-->"'
	    + '   size="<!--INPUT_FIELD_SIZE-->"'
	    // + ' onBlur="<!--HANDLER--> return false;"'
	    + '   >' //
	    + ' <input type="button" value="Ok" onclick="<!--HANDLER-->" style="border-width:thin;">'
	    + '</form>';

    var inputSize = 25;
    var inputFieldValueEscaped = escapeHtml(inputFieldValue).replace(/"/g,
	    '&quot;');

    return template_simple_edit_form.replace(/<!--HANDLER-->/g, actionHandler)
	    .replace('<!--INPUT_FIELD_ID-->', inputFieldID).replace(
		    '<!--INPUT_FIELD_VALUE-->', inputFieldValueEscaped)
	    .replace('<!--INPUT_FIELD_SIZE-->', inputSize);
}


function renderEventLink(caption, function_invok_str) {
    return renderEventLink(caption, function_invok_str, null, null);
}

function renderEventLink(caption, function_invok_str, style) {
    return renderEventLink(caption, function_invok_str, style, null);
}

function renderEventLink(caption, function_invok_str, style, cssclass) {
    var template_simpleLink = '<a href="#" onClick="<!--HANDLER--> return false;"' + '<!--STYLE--> <!--CSSCLASS--> ><!--CAPTION--></a>';

    var style_html = '';
    var cssclass_html = '';

    if (style != null) {
	style_html = ' style="' + style + '" ';
    }
    if (cssclass != null) {
	cssclass_html = ' class="' + cssclass + '" ';
    }

    return template_simpleLink.replace('<!--HANDLER-->', function_invok_str)
	    .replace('<!--STYLE-->', style_html).replace('<!--CSSCLASS-->',
		    cssclass_html).replace('<!--CAPTION-->', caption);
}

function createAttribute(name, value) {
    return ' ' + name + '="' + value + '" ';
}


function renderViewerImage(voteId, participantId) {
    var template_userImage = '<img src="<!--IMG-->" border="0" title="<!--NAME-->" ' + ' width="40" height="40">';

    var participant = wave.getParticipantById(participantId);

    var image = participant.getThumbnailUrl();
    var name = escapeHtml(participant.getDisplayName());

    var userImage = template_userImage.replace('<!--IMG-->', image).replace(
	    '<!--NAME-->', name);

    if (participantId == getWaveViewerId()) {
	userImage = wrapIntoRemoveLink(voteId, userImage);
    }
    return userImage;
}

function wrapIntoRemoveLink(voteId, userImage) {
    var handler = "removeVote('" + voteId + "');";
    return renderEventLink(userImage, handler);
}


function renderTitleSpan(title) {
    var state = wave.getState();
    var isLocked = (state.get('locked', 0) == 1);

    var handler = 'editTitle(); return false;';
    var attr = createAttribute('id', 'title')
	    + createAttribute('onClick', handler);

    if (isWaveHost() || !isLocked) {
	attr += createAttribute('style', 'cursor:pointer;');
    }

    return '<span ' + attr + '>' + escapeHtml(title) + '</span>';
}